#include "FABase/thread_pool.h"

CYKThreadGroup::CYKThreadGroup()
{

}

CYKThreadGroup::~CYKThreadGroup()
{

}


bool CYKThreadGroup::addThread(CYKAutoThread thread) {
	try {
		_threads.push_back(thread);
	}
	catch (std::bad_alloc&) {
		return false;
	}
	return true;
}

bool CYKThreadGroup::join() {
	citr_type citr;

	for (citr = _threads.begin(); citr != _threads.end(); ++citr) {
		(*citr)->join();
	}

	_threads.clear();

	return true;
}

size_t CYKThreadGroup::size() {
	return _threads.size();
}

bool CYKThreadGroup::terminateAll() {
	citr_type citr;

	for (citr = _threads.begin(); citr != _threads.end(); ++citr) {
		(*citr)->stop();
	}

	return true;
}

//////////////////////////////////////////////////////////////////////////

CYKThreadPoolRunner::CYKThreadPoolRunner(CYKThreadPool* tp)
:_tp(tp)
{

}

int32_t CYKThreadPoolRunner::operator()(const bool* isstopped, void* param)
{
	while (!(*isstopped)) {
		RunnableAutoPt pr(0);
		if (_tp->getTask().get(pr, THREADPOOL_GET_TASK_TIMEOUT) == 0 && pr.isValid()){
			(*pr)(isstopped, param);
		}
	}
	return 1;
}

//////////////////////////////////////////////////////////////////////////

CYKThreadPool::CYKThreadPool()
:_state(UNINITIALIZED)
{

}

CYKThreadPool::~CYKThreadPool() {
	terminate();
}

int CYKThreadPool::init(int nThreads) {
	int ret = 0;
	if (UNINITIALIZED == _state) {
		_state = INITIALIZED;

		addWorker(nThreads);
	}

	return ret;
}

bool CYKThreadPool::addTask(RunnableAutoPt& pr) {
	return 0 == _tasks.put(pr);
}

bool CYKThreadPool::join() {
	return _threadGroup.join();
}

size_t CYKThreadPool::size() {
	return _threadGroup.size();
}

bool CYKThreadPool::terminate() {
	return _threadGroup.terminateAll();
}

int CYKThreadPool::addWorker(int nWorker) {
	int ret = 0;
	for (int i = 0; i < nWorker; ++i) {
		IRunnable * pr = new CYKThreadPoolRunner(this);
		RunnableAutoPt pt(pr);
		CYKAutoThread workerThread(new CYKThread(pt));
		bool ok = workerThread->start();
		if (ok && workerThread.isValid()) {
			_threadGroup.addThread(workerThread);
			++ret;
		}
	}
	return ret;
}